#ifndef _MULTI_MALLOC_H
#define _MULTI_MALLOC_H

#include "stdlib.h"
#include "mytype.h"

#ifdef __cplusplus
extern "C"
{
#endif

#define MULTI_MEM_ERR_NONE 0
#define MULTI_MEM_ERR_BLOCKS 1
#define MULTI_MEM_ERR_MEM_BASE 2
#define MULTI_MEM_ERR_BLOCK_SIZE 3

	typedef struct
	{
		uu8 init_ok;   
		uu8 err;	   
		uu32 used_now; 
		uu32 used_max; 
	} multi_malloc_info_type;

	typedef struct
	{
		void *(*malloc)(size_t size);
		void *(*calloc)(size_t num, size_t size);
		void *(*realloc)(void *, size_t size);
		void (*free)(void *);
		uu16 (*perused)(void);
	} multi_malloc_api_type;

	typedef struct
	{
		uu64 *mem;						  
		uu16 *mem_tab;					  
		uu32 mem_size;					  
		uu16 block_size;				  
		uu32 block_amount;				  
		uu16 (*lock)(void);				  
		void (*unlock)(void);			  
		multi_malloc_info_type *info;	  
		const multi_malloc_api_type *api; 
	} multi_malloc_type;

	void multi_malloc_init(const multi_malloc_type *obj);
	void *multi_malloc(const multi_malloc_type *obj, size_t size);
	void *multi_calloc(const multi_malloc_type *obj, size_t num, size_t size);
	void *multi_realloc(const multi_malloc_type *obj, void *, size_t size);
	void multi_free(const multi_malloc_type *obj, void *);
	uu16 multi_malloc_perused(const multi_malloc_type *obj);

#define multi_malloc_api_name(obj) &obj##_api
#define multi_malloc_api_ref(obj) const multi_malloc_api_type obj##_api
#define multi_malloc_api_link(obj) obj.api = obj##_api 

#define multi_malloc_api_make(obj)                                       \
	void *obj##_malloc(size_t size) { return multi_malloc(&obj, size); } \
	void *obj##_calloc(size_t num, size_t size)                          \
	{                                                                    \
		return multi_calloc(&obj, num, size);                            \
	}                                                                    \
	void *obj##_realloc(void *p, size_t size)                            \
	{                                                                    \
		return multi_realloc(&obj, p, size);                             \
	}                                                                    \
	void obj##_free(void *p) { multi_free(&obj, p); }                    \
	uu16 obj##_perused(void) { return multi_malloc_perused(&obj); }      \
	const multi_malloc_api_type obj##_api = {                            \
		obj##_malloc,                                                    \
		obj##_calloc,                                                    \
		obj##_realloc,                                                   \
		obj##_free,                                                      \
		obj##_perused}

#ifdef __cplusplus
}
#endif

#endif
